#include "VSqlProcessor.h"
#include "VMain.h"

#define NUL_VAL "NULL"

VSqlProcessor* VSqlProcessor::_pthis = NULL;

enum { LOCK_DELAY = 1 };

VSqlProcessor::VSqlProcessor() :
    _event_list(),
    _result_list(),
    _processing_id(0),
    _mysqlite(NULL)
{
    VSqlProcessor::_pthis = this;
    VMain::resetIncreament(INC_SQL_EVENT_ID);
    // inc id begin from 1 and more
    VMain::getIncreament(INC_SQL_EVENT_ID);

    setCallback((thread_callback_t)&thread_callback);
}

VSqlProcessor::~VSqlProcessor()
{
}


bool VSqlProcessor::putevent(
    int request_type,
    int result_type,
    int priority,
    const std::string& sql,
    int* id)
{
    sql_event_t t_event;
    sql_event_list_t::iterator it;

    if (!verify_event(&request_type, &result_type, &priority, sql))
    {
        return false;
    }

    t_event.id = VMain::getIncreament(INC_SQL_EVENT_ID);
    t_event.type = request_type;
    t_event.priority = priority;
    t_event.sql = sql;

    if (id)
    {
        *id = t_event.id;
        t_event.result_type = result_type;
    }
    else
    {
        // 没有id的情况下, 设置该请求事件不返回
        t_event.result_type = SQL_RESULT_NONEEDED;
    }

    lock_event_list();

    if (t_event.priority == SQL_PRIORITY_INSTANT)
    {

        _event_list.push_front(t_event);

        unlock_event_list();
        return true;
    }

    for (it = _event_list.begin(); it != _event_list.end(); ++it)
    {
        if (t_event.priority < it->priority)
        {
            _event_list.insert(it, t_event);

            unlock_event_list();
            return true;
        }
    }

    _event_list.push_back(t_event);

    unlock_event_list();

    return true;
}

bool VSqlProcessor::getevent(sql_event_t* event)
{
    sql_event_list_t::iterator it;


    if (_event_list.size() == 0)
    {
        return false;
    }

    lock_event_list();

    it = _event_list.begin();

    event->id = it->id;
    event->priority = it->priority;
    event->result_type = it->result_type;
    event->sql = it->sql;
    event->type = it->type;

    _event_list.pop_front();

    unlock_event_list();

    return true;
}

bool VSqlProcessor::getresult(
    int id,
    sql_result_t* result,
    int timeout)
{
    int lasttime = VMain::getClock();
    sql_result_list_t::iterator it;

    lock_result_list();

    if ((_result_list.size() == 0) && (_event_list.size() == 0) && (get_processing_id() == 0))
    {
        unlock_result_list();
        return false;
    }

    unlock_result_list();

    if (result == NULL)
    {
        return false;
    }

    // unlock_result_list();

    // 没有找到
    if (get_processing_id() == 0)   // 处理器空闲中
    {
        //    return false;
    }

    if (check_event_list(id))   // 如果还没有处理此Event，则把它的优先级设置到最高（实时），优先处理
    {
        enhance_event_priority(id);
        VMain::delay(1);
    }

    if ((get_processing_id() == id) || check_event_list(id))  // 正在处理这个事件，或者还没有处理到。
    {
        while ((get_processing_id() == id) || check_event_list(id))
        {
            if (timeout == SQL_TIMEOUT_INFINITY)  // 永远等待
            {
                VMain::delay(SQL_WAITRESULT_DELAY);

                continue;
            }

            if (VMain::getClock() - lasttime >= timeout)   // 等待超时
            {
                unlock_result_list();
                return false;
            }
            else
            {
                VMain::delay(SQL_WAITRESULT_DELAY);
            }
        }

        unlock_result_list();
        return getresult(id, result, timeout);
    }

    lock_result_list();

    for (it = _result_list.begin(); it != _result_list.end(); ++it) // 检查结果队列
    {
        if (it->id == id)
        {
            result->id = it->id;
            result->type = it->type;
            result->errorcode = it->errorcode;
            result->errormsg = it->errormsg;
            result->content = it->content;

            _result_list.erase(it);

            unlock_result_list();
            return true;
        }
    }


    unlock_result_list();
    // 根本没有此事件
    return false;
}


// bool VSqlProcessor::getresult(int id, sql_result_t*  result, int timeout)
// {
//
//  int lasttime = VMain::getClock();
//     sql_result_list_t::iterator it;
//
//     lock_result_list();
//
//     for (it = _result_list.begin(); it != _result_list.end(); ++it)
//     {
//         if (it->id == id)
//         {
//             if (!result)
//             {
//                 return false;
//             }
//
//             result->id = it->id;
//             result->type = it->type;
//             result->errorcode = it->errorcode;
//             result->errormsg = it->errormsg;
//             result->content = it->content;
//
//             _result_list.erase(it);
//             return true;
//         }
//     }
//
//     unlock_result_list();
//     // 没有找到
//
//     if (get_processing_id() == 0)   // 处理器空闲中
//     {
//         return false;
//     }
//
//     if (get_processing_id() == id)  // 正在处理这个事件
//     {
//         while (get_processing_id() == id)
//         {
//             if (timeout == -1)  // 永远等待
//             {
//              VMain::delay(SQL_WAITRESULT_DELAY);
//
//                 continue;
//             }
//
//             if (VMain::getClock() - lasttime >= timeout)   // 等待超时
//             {
//                 return false;
//             }
//             else
//             {
//                 VMain::delay(SQL_WAITRESULT_DELAY);
//             }
//         }
//
//         return getresult(id, result, timeout);
//     }
// }


VSqlProcessor* VSqlProcessor::init_instance()
{
    if (_pthis != NULL)
    {
        return _pthis;
    }

    return new VSqlProcessor;
}

void VSqlProcessor::kill_instance()
{
    if (_pthis != NULL)
    {
        delete _pthis;
        _pthis = NULL;
    }
}

int VSqlProcessor::thread_callback(VSqlProcessor* pthis)
{
    sql_event_t sql_event;
    sql_result_t result;
    char* errmsg = NULL;
    int errcode = 0;

    for (; ;)
    {
        if (pthis->getevent(&sql_event))
        {
            pthis->set_processing_id(sql_event.id);    // 正在忙一个事件的查询工作

            init_result(&result);

            result.id = sql_event.id;
            result.type = sql_event.result_type;

            // 给result.content分配空间
            switch (result.type)
            {
            case SQL_RESULT_NONE:
                // fall through
            case SQL_RESULT_NONEEDED:
                result.content = NULL;
                break;
            case SQL_RESULT_TABLE:
                result.content = new sql_result_table_t;
                break;
            case SQL_RESULT_ROW:
                result.content = new sql_result_row_t;
                break;
            case SQL_RESULT_COLUMN:
                result.content = new sql_result_column_t;
                break;
            case SQL_RESULT_VALUE:
                result.content = new sql_result_value_t;
                break;
            default:
                ;
            }

            switch (sql_event.type)
            {
            case SQL_REQUEST_DDL:
                // fall through
            case SQL_REQUEST_DML:
                errcode = sqlite3_exec(get_this()->_mysqlite, sql_event.sql.c_str(),
                                       NULL, NULL, &errmsg);
                break;

            case SQL_REQUEST_DQL:
                errcode = sqlite3_exec(get_this()->_mysqlite, sql_event.sql.c_str(),
                                       &VSqlProcessor::sqlite_callback, &result, &errmsg);
                break;
            default:
                ;
            }

            if (errmsg)
            {
                result.errormsg = errmsg;
                sqlite3_free(errmsg);
                errmsg = NULL;
            }
            else
            {
                result.errormsg = "Successed!";
            }

            result.errorcode = errcode;
            result.processedtime = VMain::getClock();

            pthis->putresult(result);

            pthis->set_processing_id(0);   // 空闲
        }

        // 回收超时垃圾
        pthis->garbage_realese();

        VMain::delay(SQL_PROCESSOR_DELAY);
    }
}


int VSqlProcessor::sqlite_callback(void* t_result, int argc, char** argv, char** colname)
{
    sql_result_t* result = (sql_result_t*)t_result;
    int i;

    if (result->type == SQL_RESULT_NONEEDED)
    {
        // DO NOTHING
    }
    else if (result->type == SQL_RESULT_TABLE)
    {
        sql_result_table_t* tbl = (sql_result_table_t*)result->content;
        std::vector<std::string> record;

        if (tbl->headers.empty())
        {
            for (i = 0; i != argc; ++i)
            {

                if (colname[i] != NULL)
                {
                    tbl->headers.push_back(colname[i]);
                }
                else
                {
                    tbl->headers.push_back(NUL_VAL);
                }
            }
        }

        for (i = 0; i != argc; ++i)
        {
            if (argv[i] != NULL)
            {
                record.push_back(argv[i]);
            }
            else
            {
                record.push_back(NUL_VAL);
            }
        }

        tbl->data.push_back(record);
    }
    else if (result->type == SQL_RESULT_COLUMN)
    {
        sql_result_column_t* col = (sql_result_column_t*)result->content;

        if (col->header.empty())
        {
            if (argc != 0)
            {
                if (colname[0] != NULL)
                {
                    col->header = colname[0];
                }
                else
                {
                    col->header = NUL_VAL;
                }
            }
        }

        if (argc != 0)
        {
            col->column.push_back(argv[0]);
        }
    }
    else if (result->type == SQL_RESULT_ROW)
    {
        sql_result_row_t* row = (sql_result_row_t*)result->content;

        if (row->rows.empty())
        {
            for (i = 0; i != argc; ++i)
            {
                if (argv[i] != NULL)
                {
                    row->rows.push_back(argv[i]);
                }
                else
                {
                    row->rows.push_back(NUL_VAL);
                }
            }
        }
    }
    else if (result->type == SQL_RESULT_VALUE)
    {
        sql_result_value_t* value = (sql_result_value_t*)result->content;

        if (value->value.empty())
        {
            if (argv[0] != NULL)
            {
                value->value = argv[0];
            }
            else
            {
                value->value = NUL_VAL;
            }
        }
    }


    return 0;
}


bool VSqlProcessor::verify_event(int* sql_type, int* ret_type, int* priority, const std::string& sql) const
{
    // TODO: 做些插入数据是否合法的验证
    UNUSED(sql_type);
    UNUSED(ret_type);
    UNUSED(priority);
    UNUSED(sql);

    return true;
}


void VSqlProcessor::set_processing_id(int id)
{
    _pthis->_processing_id = id;
}

int VSqlProcessor::get_processing_id()
{
    return _pthis->_processing_id;
}


void VSqlProcessor::lock_event_list()
{
    if (this->_event_list_lock == LOCK_LOCKED)
    {
        while (this->_event_list_lock != LOCK_UNLOCKED)
        {
            VMain::delay(LOCK_DELAY);
        }
    }

    _event_list_lock = LOCK_LOCKED;
}

void VSqlProcessor::unlock_event_list()
{
    _event_list_lock = LOCK_UNLOCKED;
}

void VSqlProcessor::lock_result_list()
{
    if (this->_result_list_lock == LOCK_LOCKED)
    {
        while (this->_result_list_lock != LOCK_UNLOCKED)
        {
            VMain::delay(LOCK_DELAY);
        }
    }

    _result_list_lock = LOCK_LOCKED;
}
void VSqlProcessor::unlock_result_list()
{
    _result_list_lock = LOCK_UNLOCKED;
}

void VSqlProcessor::putresult(const sql_result_t& result)
{
    lock_result_list();

    _result_list.push_back(result);

    unlock_result_list();
}

VSqlProcessor* VSqlProcessor::get_this()
{
    return _pthis;
}


bool VSqlProcessor::open_database(const std::string& db_path)
{
    if (this->_mysqlite)
    {
        this->close_database();
    }

    if (sqlite3_open(db_path.c_str(), &(this->_mysqlite)) == SQLITE_OK)
    {
        return true;
    }

    return false;
}



void VSqlProcessor::close_database()
{
    if (this->_mysqlite)
    {
        sqlite3_close(this->_mysqlite);
        this->_mysqlite = NULL;
    }
}

void VSqlProcessor::free_result_content(sql_result_t* result)
{
    if (result->content)
    {
        switch (result->type)
        {
        case SQL_RESULT_TABLE:
            delete result_to_table(result);
            break;

        case SQL_RESULT_ROW:
            delete result_to_row(result);
            break;

        case SQL_RESULT_COLUMN:
            delete result_to_column(result);
            break;

        case SQL_RESULT_VALUE:
            delete result_to_value(result);
            break;

        default:
            ;
        }

        result->content = NULL;
    }
}

bool VSqlProcessor::check_event_list(int event_id)
{
    sql_event_list_t::const_iterator it;

    lock_event_list();

    if (!_event_list.size())
    {
        unlock_event_list();
        return false;
    }

    for (it = _event_list.begin();
            it != _event_list.end();
            ++it)
    {
        if (it->id == event_id)
        {
            unlock_event_list();
            return true;
        }
    }

    unlock_event_list();
    return false;
}

void VSqlProcessor::enhance_event_priority(int event_id)
{
    sql_event_list_t::iterator it;
    sql_event_t event;


    lock_event_list();

    for (it = _event_list.begin();
            it != _event_list.end();
            ++it)
    {
        if (event_id == it->id)
        {
            if (it->priority == SQL_PRIORITY_INSTANT)
            {
                unlock_event_list();
                return;
            }

            event.id = it->id;
            event.priority = SQL_PRIORITY_INSTANT;
            event.result_type = it->result_type;
            event.sql = it->sql;
            event.type = it->type;

            _event_list.erase(it);

            _event_list.push_front(event);

            unlock_event_list();
            return;
        }
    }

    unlock_event_list();
}

int VSqlProcessor::garbage_realese()
{
    sql_result_list_t::iterator it;
    static int currenttime;
    int released = 0;

    currenttime = VMain::getClock();

    lock_result_list();

    if (_result_list.empty()) {
        unlock_result_list();
        return 0;
    }

    for (it = _result_list.begin();
            it != _result_list.end();
            ++it)
    {
        if (currenttime - it->processedtime >= SQL_GARBAGE_RELEASER_TIMEOUT)
        {
            writeLog(
                "sql garbage released: "
                "id:%d, "
                "type:%d, "
                "content:[ignore], "
                "errorcode:%d, "
                "errormessage:%s, "
                "processed at:%d, "
                "relased at:%d",
                it->id,
                it->type,
                it->errorcode,
                it->errormsg.c_str(),
                it->processedtime);

            VSqlProcessor::free_result_content(&(*it));
            it = _result_list.erase(it);

            ++released;
            //
            //             if (_result_list.size() == 0)
            //             {
            //                 return released;
            //             }
        }
    }

    unlock_result_list();

    return released;
}

sql_result_table_t* VSqlProcessor::result_to_table(const sql_result_t* result)
{
    return (sql_result_table_t*)(result->content);
}

sql_result_column_t* VSqlProcessor::result_to_column(const sql_result_t* result)
{
    return (sql_result_column_t*)(result->content);
}

sql_result_value_t* VSqlProcessor::result_to_value(const sql_result_t* result)
{
    return (sql_result_value_t*)(result->content);
}

sql_result_row_t* VSqlProcessor::result_to_row(const sql_result_t* result)
{
    return (sql_result_row_t*)(result->content);
}

void VSqlProcessor::init_result(sql_result_t* result)
{
    result->content = NULL;
    result->errorcode = 0;
    result->errormsg.clear();
    result->id = 0;
    result->type = SQL_RESULT_NONE;
    result->processedtime = 0;
}
